import { DefaultOptions, Options, TrackerConfig, reportTrackerData } from '../types/core'

import { historyEvent } from '../utils/pv'
export default class EventTraker {
    public data: Options
    private varsion: string | undefined
    public constructor(options: Options) {
        //把用户传入的配置 和默认配置合并
        console.log(options)
        this.data = Object.assign(this.initDefault(), options)
        this.registerConfig()
        //根据用户传入的配置 生成相关的事件跟踪
    }
    //设置用户唯一键
    public setUuid<T extends DefaultOptions['uuid']>(uuid: T) {
        this.data.uuid = uuid
    }

    public setExtra<T extends DefaultOptions['extra']>(extra: T) {
        this.data.extra = extra
    }
    //手动上报
    public sendTraker<T extends reportTrackerData>(data: T) {
        this.sendReport(data)
    }

    //初始化参数
    private initDefault(): DefaultOptions {
        this.varsion = TrackerConfig.version
        window.history['pushState'] = historyEvent('pushState')
        window.history['replaceState'] = historyEvent('replaceState')
        return <DefaultOptions>{
            historyTracker: false,
            hashTracker: false,
            domTracker: false,
            sdkVersion: this.varsion,
            jsError: false,
        }
    }

    //注册options 传入的监听函数
    private registerConfig() {
        //history 路由模式监听上报
        if (this.data.historyTracker) {
            this.captureEvents(['pushState'], 'history-pv')
            this.captureEvents(['replaceState'], 'history-pv')
            this.captureEvents(['popstate'], 'history-pv')


        }
        //hash路由模式监听上报
        if (this.data.hashTracker) {

            this.captureEvents(['hashchange'], 'hash-pv')
        }
        //dom事件触发监听上报
        if (this.data.domTracker) {
            this.domEventTracker()
        }
        //js 报错 监听上报
        if (this.data.jsError) {
            this.jsError()
        }

    }
//注册事件派发
    private captureEvents<T>(methodsList: string[], targetKey: string, data?: T) {
        methodsList.forEach(event => {
            window.addEventListener(event, () => {
                console.log(event)
                this.sendReport({ event, targetKey, data })
            })
        })

    }

    private domEventTracker() {
      
        this.data.methodsList?.forEach(event => {
            window.addEventListener(event, (e) => {
             
                const target = e['target'] as HTMLElement
                const targetKey = target.getAttribute('traker-key')
                console.log(targetKey)
                if (targetKey) {
                    this.sendReport({ event, targetKey })
                }

            })
        })
    }
    //js控制台报错监听
    private jsError() {
        this.codeErrorEvent()
        this.promiseReject()
    }
 //js 代码报错监听
    private codeErrorEvent() {
        window.addEventListener('error', (event) => {
            this.sendReport({ event, targetKey: 'error', data: event.message })
        })
    }

    //js 异步请求报错监听
    private promiseReject() {
        window.addEventListener('unhandledrejection', (event) => {
            event.promise.catch(error => {
                this.sendReport({ event: 'promise', targetKey: 'reject', data: error })
            })

        })
    }

    //发送监听请求
    private sendReport<T>(data: T) {
        let params = Object.assign(this.data, data, { time: Date.now() })
        let headers = {
            type: 'application/x-www-form-urlencoded'
        };
        let bolb = new Blob([JSON.stringify(params)], headers)
        navigator.sendBeacon(this.data.requestUrl, bolb)

    }

}